#/usr/bin/tclsh
proc sleep {N} {
   after [expr {int($N * 100)}]
}

set NIOS_RAM_WIDTH	12
set COD_RAM_ADDR_WIDTH	8
set X_NODE_NUM	4
set Y_NODE_NUM	3
set NIOS2_RESET_ADDR 	"4000"


proc log2 {N} {
	
	global X_NODE_NUM
	global Y_NODE_NUM
	 if { $N == 0 }  {
	   return 0
	 } else {
	 	set N [expr $N-1]
         	set log 0
         	while {$N>0} {
			 set N [expr $N >> 1 ] 
			 incr log	
		}
       		return $log
	}     
}

set 	X_NODE_NUM_WIDTH	[log2 { $X_NODE_NUM 	}]
set	Y_NODE_NUM_WIDTH	[log2 {	$Y_NODE_NUM	}]

proc send_cmd { cmd } {
	#puts $cmd
	global CORE_ADDR	
	if 		{ $cmd == "reset_niose" 	  } {
		set cmd_code [expr $CORE_ADDR + 8]
 
	} elseif 	{ $cmd == "send_first_pck" } {
		set cmd_code [expr $CORE_ADDR + 11]
	
	} elseif	{ $cmd == "send_pck"	  } {
		set cmd_code [expr $CORE_ADDR + 9  ]

	} elseif	{ $cmd == "send_last_pck"  } {
		set cmd_code [expr $CORE_ADDR + 13 ]

	} elseif { $cmd== "clear"		 } {
		set cmd_code 0
	} else  {
		set usage "send_cmd ? \"reset_niose\" or \"send_first_pck\" or  \"send_pck\" or \"send_last_pck \"clear\"  "
		error $usage
	}

	set cmd_code [format %4.8X $cmd_code]
	write_content_to_memory -instance_index 1 -start_address 0 -word_count 1 -content $cmd_code -content_in_hex

}


set code_ram_size [expr 1 <<($COD_RAM_ADDR_WIDTH+2)]

scan $NIOS2_RESET_ADDR "%x"  NIOS2_RESET_HEX
puts $NIOS2_RESET_HEX 
puts $code_ram_size



set ram_required	[expr 1 << ($NIOS_RAM_WIDTH-$COD_RAM_ADDR_WIDTH)]
puts $ram_required

puts "read args"
# read core address and programe file 
set usage "prog.tcl ?-x_axe number? -y_axe number ?   -filename filename"
set i [llength $argv]
set j	0
if { $i == 0} { error $usage}
while {$i>0} {
    if {[lindex $argv $j] eq "-x_axe"} {
        set x_axe [lindex $argv [expr {$j + 1}]]
        puts $x_axe
    	 set i [expr {$i - 2}]
	 set j [expr {$j + 2}]
     
	} elseif {[lindex $argv $j] eq "-y_axe"} {
        set y_axe [lindex $argv [expr {$j + 1}]]
      	puts $y_axe
    	 set i [expr {$i - 2}]
	 set j [expr {$j + 2}]
     
	} elseif {[lindex $argv $j] eq "-filename"} { 
	 set file_name [lindex $argv [expr {$j + 1}]]
         puts $file_name
    	 set i [expr {$i - 2}]
	 set j [expr {$j + 2}]
	
	} else { error $usage
	}

 
  } 


set CORE_ADDR [expr ((($x_axe << $Y_NODE_NUM_WIDTH) + $y_axe) << 4)]




# List all available programming hardware, and select the USB-Blaster.
# (Note: this example assumes only one USB-Blaster is connected.)
puts "Programming Hardware:"
foreach hardware_name [get_hardware_names] {
	puts $hardware_name
	if { [string match "USB-Blaster*" $hardware_name] } {
		set usbblaster_name $hardware_name
	}
}
puts "\nSelect JTAG chain connected to $usbblaster_name.\n";

# List all devices on the chain, and select the first device on the chain.
puts "\nDevices on the JTAG chain:"
foreach device_name [get_device_names -hardware_name $usbblaster_name] {
	puts $device_name
	if { [string match "@1*" $device_name] } {
		set test_device $device_name
	}
}

# Initiate a editing sequence
begin_memory_edit -hardware_name $usbblaster_name -device_name $test_device

#resetting all niose
 send_cmd {reset_niose} 


set i 0

for {set i 0} {$i<$ram_required} {incr i} {
	#change elf to hex 	
	set start_addr		 [expr $NIOS2_RESET_HEX+ ($i* $code_ram_size)]
	set end_addr		 [expr $NIOS2_RESET_HEX+ (($i+1) * $code_ram_size)-1];	
#	../software/blink_led/blink_led.elf
	set cmd 			 [  format " elf2hex $file_name 0x%X 0x%X  --width=32 --little-endian-mem --create-lanes=0  mem_init/ram%d.hex"\
 $start_addr  $end_addr  $i]	
	eval exec  $cmd
	#update prog memory
	 update_content_to_memory_from_file -instance_index 0 -mem_file_path mem_init/ram$i.hex -mem_file_type hex
	#reset all microes
	

# send ram data to nios memory
if { $i == 0} { 
	send_cmd {send_first_pck}
} elseif { $i == [ expr $ram_required-1]} { 
	send_cmd {send_last_pck}
} else { 
	 send_cmd {send_pck}
}
	
	set done	0
	while { $done ==  0 } {
		set read_status  [ read_content_from_memory -instance_index 1 -start_address 0 -word_count 1 ]
               # set ram [binary format B $read_status]
                set done [expr	$read_status & 0x80000000]
		#puts $done
	}




	
}

  send_cmd {clear}

# List information of all editable memories
puts "Information on all editable memories:"
puts "index,depth,width,mode,type,name"
foreach instance [get_editable_mem_instances -hardware_name $usbblaster_name -device_name $test_device] {
	puts "[lindex $instance 0],[lindex $instance 1],[lindex $instance 2],[lindex $instance 3],[lindex $instance 4],[lindex $instance 5]"
}

# Write on prog memory
#update_content_to_memory_from_file -instance_index 0 -mem_file_path "ram1.hex" -mem_file_type hex

# write command memory
#write_content_to_memory -instance_index 1 -start_address 0 -word_count 1 -content "0000000F" -content_in_hex


#wait for end of process 





#End the editing sequence
end_memory_edit



